package com.tbl.modules.wms.util;

import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

/**
 * 使用了原始的分页方式去渲染JTextArea，提供了打印预览机制。
 * <p>
 * 事实上，我们还可以通过其他方式打印JTextArea：
 * <ol>
 * <li>{@code Component.print(Graphics g);} or
 * {@code Component.printAll(Graphics g);}</li>
 * <li>{@code Component.paint(Graphics g);} or
 * {@code Component.paintAll(Graphics g);} whose rending may be slightly
 * different to the previous method (for example, <code>JFrame</code>)</li>
 * <li>{@code JTable.print();} or {@code JTextComponent.print();} provide
 * especially powerful and convenient printing mechanism</li>
 * </ol>
 *
 * @author Gaowen
 */
public class PrintUIComponent extends JPanel implements ActionListener,
        Printable {
    private static final long serialVersionUID = 4797002827940419724L;
    private static JFrame frame;
    private final JTextArea textAreaToPrint;
    private PrinterJob job;
    // array of page break line positions
    private int[] pageBreaks;
    private String[] textLines;
    private Header header;

    public PrintUIComponent() {
        super(new BorderLayout());
        textAreaToPrint = new JTextArea(50, 20);
        for (int i = 1; i <= 50; i++) {
            textAreaToPrint.append("sdfsdf " + i + "\n");
        }
        JScrollPane scrollPane = new JScrollPane(textAreaToPrint);
        scrollPane.setPreferredSize(new Dimension(250, 200));
        add(scrollPane, BorderLayout.CENTER);
        JButton printButton = new JButton("Print This TextArea");
        printButton.setName("printButton");
        printButton.addActionListener(this);
        JButton printPreviewButton = new JButton("Print Preview");
        printPreviewButton.setName("printPreviewButton");
        printPreviewButton.addActionListener(this);
        JPanel buttonGroup = new JPanel(new GridLayout(2, 1));
        buttonGroup.add(printButton);
        buttonGroup.add(printPreviewButton);
        add(buttonGroup, BorderLayout.SOUTH);

        /* Initialize PrinterJob */
        initPrinterJob();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(PrintUIComponent::createandshowgui);
    }

    private static void createandshowgui() {
        frame = new JFrame("Print UI Example");
        frame.setContentPane(new PrintUIComponent());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private void initTextLines() {
        Document doc = textAreaToPrint.getDocument();
        try {
            String text = doc.getText(0, doc.getLength());
            textLines = text.split("\n");
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
    }

    private void initPrinterJob() {
        job = PrinterJob.getPrinterJob();
        // 出现在系统打印任务列表
        job.setJobName("Print TextArea");
        job.setPrintable(this);
    }

    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
        /*
         * It is safe to use a copy of this graphics as this will not involve
         * changes to it.
         */
        Graphics2D g2 = (Graphics2D) graphics.create();

        /* Calculate "pageBreaks" */
        Font font = new Font("Serif", Font.PLAIN, 8);
        FontMetrics metrics = g2.getFontMetrics(font);
        int lineHeight = metrics.getHeight();
        if (pageBreaks == null) {
            initTextLines();
            int linesPerPage = (int) (pageFormat.getImageableHeight() / lineHeight);
            int numBreaks = (textLines.length - 1) / linesPerPage;
            pageBreaks = new int[numBreaks];
            for (int b = 0; b < numBreaks; b++) {
                pageBreaks[b] = (b + 1) * linesPerPage;
            }
        }

        /* Condition to exit printing */
        if (pageIndex > pageBreaks.length) {
            return NO_SUCH_PAGE;
        }

        /* (0,0) is outside the imageable area, translate to avoid clipping */
        g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

        /* Draw each line that is on this page */
        int y = 0;
        int start = (pageIndex == 0) ? 0 : pageBreaks[pageIndex - 1];
        int end = (pageIndex == pageBreaks.length) ? textLines.length
                : pageBreaks[pageIndex];
        for (int line = start; line < end; line++) {
            y += lineHeight;
            g2.drawString(textLines[line], 0, y);
        }
        g2.drawString("远东电缆物资流转单",173,50);
        g2.drawString("从厂：",10,80);
        g2.drawString("打印日期：",80,100);
        g2.drawString("至厂：",250,80);
        g2.drawString("车辆：",150,80);
        g2.drawString("单号：",250,100);
        g2.drawRect(30,120,380,250);
        g2.drawString("发货员：",10,400);
        g2.drawString("提示：发货员、门卫、驾驶员三方必须清点进出货物",10,420);
        g2.drawString("接收人：",250,400);
        g2.drawString("班次：",300,400);
        g2.drawString("门卫：",350,400);
        //在指定坐标(198,61)处 写入二维码或其它图片
//        try {
//            g2.drawImage(ImageIO.read(new File("F:/360Downloads/二维码图片/1.jpg")), null, 198, 61);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        /* dispose of the graphics copy */
        g2.dispose();

        /* Tell the caller that this page is part of the printed document */
        return PAGE_EXISTS;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object actionEventSource = e.getSource();
        if (actionEventSource instanceof JButton) {
            JButton button = (JButton) actionEventSource;
            if ("printButton".equals(button.getName())) {
                // reset pagination
                pageBreaks = null;
                boolean ok = job.printDialog();
                if (ok) {
                    try {
                        job.print();
                    } catch (PrinterException ex) {
                        /* The job did not successfully complete */
                        ex.printStackTrace();
                    }
                }
            } else if ("printPreviewButton".equals(button.getName())) {
                // reset pagination
                pageBreaks = null;
                createAndShowPreviewDialog();
            }
        }
    }

    private void createAndShowPreviewDialog() {
        JDialog previewDialog = new JDialog(frame, "Print Preview Dialog", true);
        JPanel contentPane = new JPanel(new BorderLayout());
        PreviewArea previewArea = new PreviewArea();
        previewArea.addMouseListener(new PreviewAreaMouseAdapter(previewArea));
        JScrollPane scrollPane = new JScrollPane(previewArea);
        contentPane.add(scrollPane, BorderLayout.CENTER);
        header = new Header(previewArea);
        contentPane.add(header, BorderLayout.NORTH);
        previewDialog.setContentPane(contentPane);
        previewDialog.setSize(600, 600);
        previewDialog
                .setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        previewDialog.setVisible(true);
    }

    private class Header extends Component {
        private static final long serialVersionUID = -1741188309769027249L;
        private final PreviewArea previewArea;
        private boolean paintable;

        private Header(PreviewArea previewArea) {
            this.previewArea = previewArea;
        }

        private void setPaintable() {
            this.paintable = true;
        }

        @Override
        public void paint(Graphics g) {
            if (paintable) {
                g.setColor(Color.GRAY);
                g.drawString(
                        (previewArea.getPageIndex() + 1)
                                + "/"
                                + (pageBreaks.length + 1)
                                + " pages (Click left mouse button to preview next page; right to previous)",
                        10, 15);
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(super.getPreferredSize().width, 20);
        }
    }

    private class PreviewArea extends Component {
        private static final long serialVersionUID = -6384174997251439843L;
        private final PageFormat pageFormat;
        private int pageIndex;
        private final int w;
        private final int h;
        private final int marginX = 10;
        private final int marginY = 20;

        private PreviewArea() {
            pageFormat = job.pageDialog(job.defaultPage());
            pageIndex = 0;
            w = (int) pageFormat.getWidth();
            h = (int) pageFormat.getHeight();
        }

        private int getPageIndex() {
            return pageIndex;
        }

        private void setPageIndex(int pageIndex) {
            this.pageIndex = pageIndex;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(w + 2 * marginX, h + 2 * marginY);
        }

        @Override
        public void paint(Graphics g) {
            Graphics2D g2 = (Graphics2D) g.create();
            g2.translate(marginX, marginY);
            g2.drawRect(0, 0, w, h);
            int ix = (int) (pageFormat.getImageableX() - 1);
            int iy = (int) (pageFormat.getImageableY() - 1);
            int iw = (int) (pageFormat.getImageableWidth() + 1);
            int ih = (int) (pageFormat.getImageableHeight() + 1);
            g2.setStroke(new BasicStroke(1f, BasicStroke.CAP_ROUND,
                    BasicStroke.JOIN_ROUND, 10f, new float[] { 5, 5 }, 0f));
            g2.drawRect(ix, iy, iw, ih);
            PrintUIComponent.this.print(g2, pageFormat, pageIndex);
            g2.dispose();
            header.setPaintable();
            header.repaint();
        }
    }

    private class PreviewAreaMouseAdapter extends MouseAdapter {
        private final PreviewArea previewArea;

        private PreviewAreaMouseAdapter(PreviewArea previewArea) {
            this.previewArea = previewArea;
        }

        @Override
        public void mouseClicked(MouseEvent e) {
            int currentIndex = previewArea.getPageIndex();
            if (e.getButton() == MouseEvent.BUTTON1) {
                /* next page */
                if (currentIndex < pageBreaks.length) {
                    previewArea.setPageIndex(currentIndex + 1);
                    previewArea.repaint();
                }
            } else if (e.getButton() == MouseEvent.BUTTON3) {
                /* previous page */
                if (currentIndex > 0) {
                    previewArea.setPageIndex(currentIndex - 1);
                    previewArea.repaint();
                }
            }
        }
    }
}